/* Copyright 2009 Requirements Management System
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.mags.remas.view.dialogs.solicitors;

import java.io.File; 
import java.sql.Connection;
import java.sql.DriverManager;

import org.apache.commons.validator.GenericValidator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Text;
import org.mags.remas.exception.SingletonExceptionHandler;
import org.mags.remas.model.commons.DataSourceInformation;
import org.mags.remas.view.dialogs.AbstractSolicitorDialog;

/**
 * 
 * @author Mario Gaitan
 *
 */
public class DerbyInformationSolicitor extends AbstractSolicitorDialog {
	private Button exploreButton;
	private Text directoryText;
	private Text descriptionText;
	private Text userText;
	private Text passwordText;
	public static final String DRIVER_NAME = "org.apache.derby.jdbc.EmbeddedDriver";
	public static final String HIBERNATE_DIALECT = "org.hibernate.dialect.DerbyDialect";
	public static final String HBM_PACKAGE = "org/mags/remas/model/derby/hbm/";
	private static final char[] ILLEGAL_CHARACTERS = { '/', '\n', '\r', '\t', '\0', '\f', '`', '?', '*', '\\', '<', '>', '|', '\"', ':' };

	public DerbyInformationSolicitor(Display display) {
		super(display);
		setMinimumSize(200, 100);
	}
	private void createDirectoryInformation(Composite parent) {
		createLabel(parent, "directory", 1);
		directoryText = createText(parent, 3, 255);
		exploreButton = createButton(parent, "explore", 1);
		exploreButton.addSelectionListener(new SelectionListener() {
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
			}
			@Override
			public void widgetSelected(SelectionEvent e) {
				changeDirectory();
			}
			
		});
	}
	private void changeDirectory() {
		DirectoryDialog directory = new DirectoryDialog(super.getShell());
		directory.setText("select project directory");
		directory.setMessage("select project directory");
		try {
			String _directory = directoryText.getText();
			if(!_directory.endsWith(File.separator))
				_directory = _directory + File.separator;
			_directory = _directory + (descriptionText.getText()==null?"":descriptionText.getText());
			directory.setFilterPath(_directory);
		} catch(Exception e){/*IGNORE EXCEPTION*/}
		String dir = directory.open();
		if(!GenericValidator.isBlankOrNull(dir))
			setDirectory(dir);
	}
	public void setDirectory(String dir) {
		directoryText.setText("");
		descriptionText.setText("");		
		Connection conn = null;
		boolean divide = false;
		try {
			Class.forName(DRIVER_NAME).newInstance();
			conn = DriverManager.getConnection("jdbc:derby:"+dir);
			divide = true;
		} catch(Exception e) {
			String key = SingletonExceptionHandler.getInstance().getKey(e);
			if(key.equals("invalidAuthentication"))
				divide = true;
		} finally {
			try {
				if(conn!=null)
					conn.close();
			} catch(Exception _e) {/*IGNORE EXCEPTION*/}			
		}
		if(divide) {
			try {
				String _dir = dir;
				if(_dir.endsWith(File.separator))
					_dir = _dir.substring(0, _dir.length()-1);
				int index = _dir.lastIndexOf(File.separator);
				String directory = _dir.substring(0, index);
				String description = _dir.substring(index+1);
				directoryText.setText(directory);
				descriptionText.setText(description);
			} catch(Exception e) {
				divide = false;
			}
		}
		if(!divide) 
			directoryText.setText(dir);
	}
	private boolean isValidFileName(String text) {
		if(GenericValidator.isBlankOrNull(text))
			return false;
		for(char c: ILLEGAL_CHARACTERS) {
			Character _c = new Character(c);
			if(text.indexOf(_c.toString())>=0)
				return false;
		}
		return true;
	}
	private void createDescriptionInformation(Composite parent) {
		createLabel(parent, "description", 1);
		descriptionText = createText(parent, 4, 25);
	}
	private void createUserInformation(Composite parent) {
		createLabel(parent, "user", 1);
		userText = createText(parent, 4, 25);
	}
	private void createPasswordInformation(Composite parent) {
		//createLabel(parent, "password", 1);
		passwordText = createPassword(parent, 4, 25);
		passwordText.setVisible(false);
	}
	@Override
	protected void createContent(Composite parent) {
		Composite composite = new Composite(parent, SWT.NONE);
		composite.setLayout(new GridLayout(5, true));
		composite.setLayoutData(getCellLayoutData());	
		createDescriptionInformation(composite);
		createDirectoryInformation(composite);
		createUserInformation(composite);
		createPasswordInformation(composite);
	}	
	@Override
	public void setInformation2Controls(DataSourceInformation dataSourceInformation) {
		if(!GenericValidator.isBlankOrNull(dataSourceInformation.getUrl())&&dataSourceInformation.getUrl().length()>11) {
			String url = dataSourceInformation.getUrl().substring(11);
			if(!GenericValidator.isBlankOrNull(dataSourceInformation.getDescription())&&url.endsWith(dataSourceInformation.getDescription())) {
				url = url.substring(0, url.lastIndexOf(dataSourceInformation.getDescription()));
			}
			directoryText.setText(url);
		}
		userText.setText(dataSourceInformation.getUsername());
		descriptionText.setText(dataSourceInformation.getDescription());
		passwordText.setText("");
	}
	@Override
	public void setInformation2Object(
			DataSourceInformation dataSourceInformation) {
		if(!directoryText.getText().endsWith(File.separator))
			directoryText.setText(directoryText.getText()+File.separator);
		dataSourceInformation.setUrl("jdbc:derby:"+directoryText.getText()+descriptionText.getText());
		dataSourceInformation.setUsername(userText.getText());
		dataSourceInformation.setDescription(descriptionText.getText());
		dataSourceInformation.setDriverClassName(DRIVER_NAME);
		dataSourceInformation.setPassword(passwordText.getText());
		dataSourceInformation.addProperty("hibernate.dialect", HIBERNATE_DIALECT);
		dataSourceInformation.addProperty("hbm_package", HBM_PACKAGE);
		dataSourceInformation.setDefaultCatalog("APP");
	}
	@Override
	public boolean equalsDriverName(String driverName) {
		return DRIVER_NAME.equals(driverName);
	}
	@Override
	public void clear() {
		directoryText.setText("");
		descriptionText.setText("");
		userText.setText("");
		passwordText.setText("");
	}
	@Override
	public String getId() {
		return "Local project";
	}
	@Override
	public boolean validate() {
		if(GenericValidator.isBlankOrNull(descriptionText.getText())) {
			SingletonExceptionHandler.getInstance().showError("description can't be empty");
			return false;
		} else if(!isValidFileName(descriptionText.getText())) {
			SingletonExceptionHandler.getInstance().showError("description must be a valid filename");
			return false;
		}	
		if(GenericValidator.isBlankOrNull(directoryText.getText())) {
			SingletonExceptionHandler.getInstance().showError("directory can't be empty");
			return false;
		}
		return true;
	}
}
